package com.huitone.smspfm.redis.impl;

import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.data.redis.RedisConnectionFailureException;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bin.common.utils.StringUtils;
import com.huitone.smspfm.redis.BaseAbstractOpts;
import com.huitone.smspfm.redis.IListOpts;
import com.huitone.smspfm.redis.model.AppCanstant;

/**
 * 
* @Title: ListOpts.java 
* @Package com.huitone.smspfm.redis.impl 
* @Description: TODO(用一句话描述该文件做什么) 
* @author ybliang   
* @date 2017年3月15日 上午10:29:11 
* @version V1.0
 */
public class ListOpts extends BaseAbstractOpts<String, String> implements IListOpts {
	
	private static final Logger logger = LogManager.getLogger(ListOpts.class);
	
	@Override
	public long push(String key, String value) {
		
		long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		long result = 0;
		
		do {
			try {
				curTryTimes ++;
				result = redisTemplate.opsForList().leftPush(key, value);
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "push(String key, String value)");
				json.put("key", key);
				json.put("value", value);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
		return result;
	}

	@Override
	public String pop(String key) {
		
		long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		String result = null;
		
		do {
			try {
				curTryTimes ++;
				result = redisTemplate.opsForList().leftPop(key);
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "pop(String key)");
				json.put("key", key);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
		return StringUtils.toString(result);
	}

	@Override
	public long in(String key, String value) {
		
		long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		long result = 0;
		
		do {
			try {
				curTryTimes ++;
				result = redisTemplate.opsForList().leftPush(key, value);
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
				
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "in(String key, String value)");
				json.put("key", key);
				json.put("value", value);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
		return result;
	}
	
	public long leftPushAll(String key, String... values) {
		
		long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		long result = 0;
		
		do {
			try {
				curTryTimes ++;
				result = redisTemplate.opsForList().leftPushAll(key, values);
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "leftPushAll(String key, String... values)");
				json.put("key", key);
				JSONArray array = new JSONArray();
				for(int i = 0 ; i < values.length ; i++){
					array.add(values[i]);
				}
				json.put("values", array);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
		return result;
	}
	
	@Override
	public String out(String key) {
		
		long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		String result = null;
		
		do {
			try {
				curTryTimes ++;
				result = redisTemplate.opsForList().rightPop(key);
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "out(String key)");
				json.put("key", key);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
		return StringUtils.toString(result);
	}
	
	public long length(String key) {
		
		long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		long result = 0;
		
		do {
			try {
				curTryTimes ++;
				result = redisTemplate.opsForList().size(key);
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "length(String key)");
				json.put("key", key);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
		return result;
	}
	
	public List<String> range(String key, long start, long end) {
		
		long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		List<String> result = new ArrayList<String>();
		
		do {
			try {
				curTryTimes ++;
				result = redisTemplate.opsForList().range(key, start, end);
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "range(String key, long start, long end)");
				json.put("key", key);
				json.put("start", start);
				json.put("end", end);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
		return result;
	}
	
    public void remove(String key, long i, String value) { 
    	
    	long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		do {
			try {
				curTryTimes ++;
				redisTemplate.opsForList().remove(key, i, value);  
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "remove(String key, long i, String value)");
				json.put("key", key);
				json.put("i", i);
				json.put("value", value);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
    }  
  
    public String index(String key, long index) {  
    	
    	long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		String result = null;
		
		do {
			try {
				curTryTimes ++;
				result = redisTemplate.opsForList().index(key, index); 
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "index(String key, long index)");
				json.put("key", key);
				json.put("index", index);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
		return StringUtils.toString(result);
    }  
  
    public void set(String key, long index, String value) {  
    	
    	long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		do {
			try {
				curTryTimes ++;
				redisTemplate.opsForList().set(key, index, value);  
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "set(String key, long index, String value)");
				json.put("key", key);
				json.put("index", index);
				json.put("value", value);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
    }  
  
    public void trim(String key, long start, int end) {  
    	
    	long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		do {
			try {
				curTryTimes ++;
				redisTemplate.opsForList().trim(key, start, end);  
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "trim(String key, long start, int end)");
				json.put("key", key);
				json.put("index", start);
				json.put("value", end);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
    	
    }

}
